#pragma once

#include <iostream>
#include <queue>
#include <pthread.h>

// 阻塞队列模板类
template <class T>
class BlockQueue
{
    // 默认队列最大容量
    static const int defalutnum = 20;
public:
    // 构造函数，初始化互斥锁和条件变量
    BlockQueue(int maxcap = defalutnum):maxcap_(maxcap)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&c_cond_, nullptr);  // 消费者条件变量
        pthread_cond_init(&p_cond_, nullptr);  // 生产者条件变量
        
        // 水位线设计（注释掉的优化方案）
        // low_water_ = maxcap_/3;     // 低水位，队列元素少于此值时通知生产者
        // high_water_ = (maxcap_*2)/3;// 高水位，队列元素多于此值时通知消费者
    }

    // 消费者接口：从队列取出元素
    T pop()
    {
        pthread_mutex_lock(&mutex_);
        
        // 使用while而不是if，防止虚假唤醒
        // 队列为空时，消费者需要等待
        while(q_.size() == 0)
        {
            // pthread_cond_wait会:
            // 1. 释放mutex_
            // 2. 阻塞等待c_cond_信号
            // 3. 收到信号后重新获取mutex_
            pthread_cond_wait(&c_cond_, &mutex_);
        }
        
        // 取出队首元素
        T out = q_.front();
        q_.pop();

        // 水位线控制（注释掉的优化方案）
        // if(q_.size() < low_water_) 
        //     pthread_cond_signal(&p_cond_);
        
        // 通知生产者可以生产
        pthread_cond_signal(&p_cond_);
        pthread_mutex_unlock(&mutex_);

        return out;
    }

    // 生产者接口：向队列放入元素
    void push(const T &in)
    {
        pthread_mutex_lock(&mutex_);
        
        // 使用while而不是if，防止虚假唤醒
        // 队列满时，生产者需要等待
        while(q_.size() == maxcap_)
        {
            pthread_cond_wait(&p_cond_, &mutex_);
        }
        
        // 放入新元素
        q_.push(in);
        
        // 水位线控制（注释掉的优化方案）
        // if(q_.size() > high_water_) 
        //     pthread_cond_signal(&c_cond_);
        
        // 通知消费者可以消费
        pthread_cond_signal(&c_cond_);
        pthread_mutex_unlock(&mutex_);
    }

    // 析构函数：清理互斥锁和条件变量
    ~BlockQueue()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&c_cond_);
        pthread_cond_destroy(&p_cond_);
    }

private:
    std::queue<T> q_;        // 底层队列容器
    //int mincap_;          // 最小容量（未使用）
    int maxcap_;            // 最大容量
    pthread_mutex_t mutex_; // 互斥锁
    pthread_cond_t c_cond_; // 消费者条件变量
    pthread_cond_t p_cond_; // 生产者条件变量

    // 水位线设计（注释掉的优化方案）
    // int low_water_;     // 低水位线
    // int high_water_;    // 高水位线
};